// See LICENSE.SiFive for license details.

package freechips.rocketchip.subsystem

import Chisel._
import freechips.rocketchip.config.{Parameters}
import freechips.rocketchip.devices.tilelink._
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.tilelink._
import freechips.rocketchip.util._
import lvna.TokenBucketNode

case class SystemBusParams(
    beatBytes: Int,
    blockBytes: Int,
    policy: TLArbiter.Policy = TLArbiter.roundRobin,
    zeroDevice: Option[AddressSet] = None,
    errorDevice: Option[DevNullParams] = None)
  extends HasTLBusParams with HasBuiltInDeviceParams

class SystemBus(params: SystemBusParams)(implicit p: Parameters)
    extends TLBusWrapper(params, "system_bus")
    with CanHaveBuiltInDevices
    with CanAttachTLSlaves
    with CanAttachTLMasters
    with HasTLXbarPhy {
  attachBuiltInDevices(params)

  def fromTile
      (name: Option[String], buffer: BufferParams = BufferParams.none, cork: Option[Boolean] = None, token: Option[TokenBucketNode] = None)
      (gen: => TLOutwardNode): NoHandle = {
//    println(s"inward node size: ${inwardNode.inward.inputs.size}")
//    println(s"outward node size: ${gen.outward.outputs.size}")
    from("tile" named name) {
      if (token.isDefined) {
        inwardNode := token.get.node :=* TLBuffer(buffer) :=* TLFIFOFixer(TLFIFOFixer.allUncacheable) :=* gen
      }
      else {
        inwardNode :=* TLBuffer(buffer) :=* TLFIFOFixer(TLFIFOFixer.allUncacheable) :=* gen
      }
    }
  }
}
